#include <stdio.h>
#include <string>
#include <iostream>

#include <cstring>
#include <dirent.h>
#include <sys/stat.h>
#include <unistd.h>


#include "opencv2/opencv.hpp"

using namespace cv;
using namespace std;

std::vector<std::string> getFiles(const std::string &folder,
                                         const bool all = true) {
	std::vector<std::string> files;
	std::list<std::string> subfolders;
	subfolders.push_back(folder);

	while (!subfolders.empty()) {
	std::string current_folder(subfolders.back());

	//cout << "string.end = " << *(current_folder.end() - 1) << endl;

	if (*(current_folder.end() - 1) != '/') {
	  current_folder.push_back('/');
	}

	DIR* pdir = opendir(current_folder.c_str());

	subfolders.pop_back();

	if (!pdir) {
	  continue;
	}

	dirent* dir = NULL;

	while ((dir = readdir(pdir)) != NULL) {
	  // iterates the current folder, search file & sub folder
	  struct stat st;

	  if (all && (!strcmp(dir->d_name, ".") || !strcmp(dir->d_name, ".."))) {
	    // must ignore . & ..
	    continue;
	  }

	  if (!strcmp(dir->d_name, ".DS_Store")) {
	    // in OSX, 'finder' will create .DS_Store
	    continue;
	  }

	  std::string file_path;

	  file_path.append(current_folder.c_str());
	  file_path.append(dir->d_name);

	  if (lstat(file_path.c_str(), &st) < 0) {
	    // perror("lstat");
	    continue;
	  }

	  if (S_ISDIR(st.st_mode)) {
	    // it's a sub folder
	    if (all) {
	      // will search sub folder
	      std::string subfolder(current_folder);
	      subfolder.append(dir->d_name);

	      subfolders.push_back(subfolder.c_str());
	    }
	  } else {
	    // it's a file
	    files.push_back(file_path);
	  }
	}  // while
	closedir(pdir);
}

return files;
}

void getPlate(Mat& trainingImages, vector<int>& trainingLabels)
{

    const char * filePath = "./has";
    vector<string> files;

    files = getFiles(filePath);

    int size = files.size();
    if (0 == size)
        cout << "No File Found in train HasPlate!" << endl;

    for (int i = 0;i < size;i++)
    {
       // cout << files[i].c_str() << endl;
        Mat img = imread(files[i].c_str());

        img= img.reshape(1, 1);
                trainingImages.push_back(img);
                trainingLabels.push_back(1);
    }
}        

void getNoPlate(Mat& trainingImages, vector<int>& trainingLabels)
{

    const char * filePath = "./no";
    vector<string> files;

    files = getFiles(filePath);
    int size = files.size();
    if (0 == size)
        cout << "No File Found in train NoPlate!" << endl;

    for (int i = 0;i < size;i++)
    {
      //  cout << files[i].c_str() << endl;
        Mat img = imread(files[i].c_str());
        
        img= img.reshape(1, 1);
                trainingImages.push_back(img);
                trainingLabels.push_back(0);
    }
}


int main()
{
	Mat classes;//(numPlates+numNoPlates, 1, CV_32FC1);
    Mat trainingData;//(numPlates+numNoPlates, imageWidth*imageHeight, CV_32FC1 );

    Mat trainingImages;
    vector<int> trainingLabels;

    getPlate(trainingImages, trainingLabels);
    getNoPlate(trainingImages, trainingLabels);

    Mat(trainingImages).copyTo(trainingData);
    trainingData.convertTo(trainingData, CV_32FC1);
    Mat(trainingLabels).copyTo(classes);


	cv::Ptr<cv::ml::SVM> svm_;
	svm_ = cv::ml::SVM::create();
	svm_->setType(cv::ml::SVM::C_SVC);
	svm_->setKernel(cv::ml::SVM::LINEAR);
	svm_->setDegree(0);
	svm_->setGamma(1); 
	svm_->setCoef0(0);
	svm_->setC(1);
	svm_->setNu(0);
	svm_->setP(0);
	svm_->setTermCriteria(cvTermCriteria(CV_TERMCRIT_ITER, 1000, 0.01));


	auto train_data = cv::ml::TrainData::create(trainingData, cv::ml::SampleTypes::ROW_SAMPLE,classes);

	svm_->train(train_data);
	svm_->save("./t_svm.xml");


	Mat img = imread("./test_pic/3.jpg");
			
	img = img.reshape(1, 1);
	img.convertTo(img, CV_32FC1);


    int response = (int)svm_->predict(img);
    if (response == 1)
    {
        printf("1 is car plate\n");
    }
	else
		printf("1 not car plate\n");


	
	
	return 0;
}

